package cn.cdeden.knowledge.service.impl;


import cn.cdeden.common.core.utils.MapstructUtils;
import cn.cdeden.common.core.utils.page.TableDataInfo;
import cn.cdeden.common.mybatis.validator.QueryHelpMybatisPlus;
import cn.cdeden.common.satoken.utils.LoginHelper;
import cn.cdeden.knowledge.domain.Team;
import cn.cdeden.knowledge.domain.TeamMember;
import cn.cdeden.knowledge.domain.TeamRole;
import cn.cdeden.knowledge.domain.dto.*;
import cn.cdeden.knowledge.enums.PermTypeEnum;
import cn.cdeden.knowledge.mapper.TeamMapper;
import cn.cdeden.knowledge.mapper.TeamMemberMapper;
import cn.cdeden.knowledge.service.TeamMemberService;
import cn.cdeden.knowledge.service.TeamRoleService;
import cn.cdeden.knowledge.utils.PageUtil;
import cn.cdeden.knowledge.utils.TeamUtils;
import cn.cdeden.system.api.RemoteDeptService;
import cn.cdeden.system.api.RemotePostService;
import cn.cdeden.system.api.RemoteRoleService;
import cn.cdeden.system.api.RemoteUserService;
import cn.cdeden.system.api.domain.vo.RemoteDeptVo;
import cn.cdeden.system.api.domain.vo.RemoteJobVo;
import cn.cdeden.system.api.domain.vo.RemoteRoleVo;
import cn.cdeden.system.api.model.LoginUser;
import cn.cdeden.knowledge.service.TeamRelevanceRoleService;
import cn.cdeden.system.api.model.RoleDTO;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.AllArgsConstructor;
import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.ObjectUtils;

import java.util.*;

/**
 * @author Chen
 * @date 2022-09-06
 */
@Service
@AllArgsConstructor
@Transactional(propagation = Propagation.SUPPORTS, readOnly = true, rollbackFor = Exception.class)
public class TeamMemberServiceImpl extends ServiceImpl<TeamMemberMapper, TeamMember> implements TeamMemberService {

    private final TeamMemberMapper teamMemberMapper;
    private final TeamRoleService teamRoleService;
    private final TeamRelevanceRoleService teamRelevanceRoleService;
    @DubboReference
    private final RemoteDeptService sysDeptService;
    @DubboReference
    private final RemoteUserService remoteUserService;
    //    private final DeptService deptService;
    @DubboReference
    private final RemoteRoleService sysRoleService;
    @DubboReference
    private final RemotePostService remotePostService;

    private final TeamMapper teamMapper;

    @Override
    public TableDataInfo<TeamMemberDto> queryAll(TeamMemberQueryParam query, Pageable pageable) {
        IPage<TeamMemberDto> page = PageUtil.toMybatisPage(pageable);
        String teamId = query.getTeamId();
        List<String> objectTypes = query.getObjectType();
        List<TeamMember> teamMembers = teamMemberMapper.queryByTeamId(teamId, query.getNickName(), pageable.getPageNumber() * pageable.getPageSize(), pageable.getPageSize(), query.getRoleId(), objectTypes);
        List<TeamMemberDto> teamMemberDtos = MapstructUtils.convert(teamMembers, TeamMemberDto.class);
        for (TeamMemberDto teamMemberDto : teamMemberDtos) {
            int objectType = teamMemberDto.getObjectType();
            //根据类型放入对象名称
            if (objectType == PermTypeEnum.USER.getPermTypeCode()) {
                //用户类型
                teamMemberDto.setObjectName(remoteUserService.getUserInfo(teamMemberDto.getObjectId()).getNickname());
            }
            if (objectType == PermTypeEnum.DEPT.getPermTypeCode()) {
                //部门类型
                teamMemberDto.setObjectName(sysDeptService.getById(teamMemberDto.getObjectId()).getDeptName());
            }
            if (objectType == PermTypeEnum.ROLE.getPermTypeCode()) {
                //系统角色类型
                teamMemberDto.setObjectName(sysRoleService.getById(teamMemberDto.getObjectId()).getRoleName());
            }
            if (objectType == PermTypeEnum.JOB.getPermTypeCode()) {
                //岗位类型
                teamMemberDto.setObjectName(remotePostService.getById(teamMemberDto.getObjectId()).getName());
            }

            TeamRole teamRole = teamRoleService.getById(teamMemberDto.getRoleId());
            teamMemberDto.setRoleName(teamRole.getRoleName());
            teamMemberDto.setRoleRank(teamRole.getRank());
        }
        int count = teamMemberMapper.queryByTeamIdCount(teamId, query.getNickName(), query.getRoleId(), objectTypes);
        page.setTotal(count);
        page.setPages(pageable.getPageNumber());
        page.setSize(pageable.getPageSize());
        page.setRecords(teamMemberDtos);
        return TableDataInfo.build(page);
    }

    @Override
    public List<TeamMemberDto> queryAll(TeamMemberQueryParam query) {
        List<TeamMember> teamMembers = teamMemberMapper.queryByTeamId(query.getTeamId(), query.getNickName(), null, null, query.getRoleId(), query.getObjectType());
        return MapstructUtils.convert(teamMembers, TeamMemberDto.class);
    }

    /**
     * 获取该用户拥有哪些成员对象
     *
     * @param userId
     * @return
     */
    @Override
    public List<TeamMemberDto> getTeamByMemberDto(Long userId) {
        //根据类型查询出所有可查看的团队
        //用户类型
        QueryWrapper<TeamMember> predicate = QueryHelpMybatisPlus.getPredicate(new TeamMemberQueryParam());
        predicate.eq("object_id", userId);
        predicate.eq("object_type", PermTypeEnum.USER.getPermTypeCode());
        Set<TeamMemberDto> teamMemberDtoList = new HashSet<>(MapstructUtils.convert(teamMemberMapper.selectList(predicate), TeamMemberDto.class));
        //部门类型
        List<RemoteDeptVo> deptALlByUser = sysDeptService.getDeptALlByUser(userId);
        if (deptALlByUser.size() > 0) {
            predicate = QueryHelpMybatisPlus.getPredicate(new TeamMemberQueryParam());
            // 循环构建或条件
            predicate.and(wrap -> {
                for (int i = 0; i < deptALlByUser.size(); i++) {
                    if (i == 0) {
                        wrap.eq("object_id", deptALlByUser.get(i).getDeptId());
                    } else {
                        wrap.or().eq("object_id", deptALlByUser.get(i).getDeptId());
                    }
                }
            });
            predicate.eq("object_type", PermTypeEnum.DEPT.getPermTypeCode());
            teamMemberDtoList.addAll(MapstructUtils.convert(teamMemberMapper.selectList(predicate), TeamMemberDto.class));
        }
        //系统角色类型
        predicate = QueryHelpMybatisPlus.getPredicate(new TeamMemberQueryParam());
        List<RemoteRoleVo> roleSmallDtos = sysRoleService.selectUserRoleByUserId(userId);
        // 循环构建或条件
        if (roleSmallDtos.size() > 0) {
            predicate.and(wrap -> {
                for (int i = 0; i < roleSmallDtos.size(); i++) {
                    if (i == 0) {
                        wrap.eq("object_id", roleSmallDtos.get(i).getRoleId());
                    } else {
                        wrap.or().eq("object_id", roleSmallDtos.get(i).getRoleId());
                    }
                }
            });
            predicate.eq("object_type", PermTypeEnum.ROLE.getPermTypeCode());
            teamMemberDtoList.addAll(MapstructUtils.convert(teamMemberMapper.selectList(predicate), TeamMemberDto.class));
        }
        //岗位类型
        predicate = QueryHelpMybatisPlus.getPredicate(new TeamMemberQueryParam());
        List<RemoteJobVo> jobDtos = remotePostService.selectUserJobByUserId(userId);
        // 循环构建或条件
        if (jobDtos.size() > 0) {
            predicate.and(wrap -> {
                for (int i = 0; i < jobDtos.size(); i++) {
                    if (i == 0) {
                        wrap.eq("object_id", jobDtos.get(i).getJobId());
                    } else {
                        wrap.or().eq("object_id", jobDtos.get(i).getJobId());
                    }
                }
            });
            predicate.eq("object_type", PermTypeEnum.JOB.getPermTypeCode());
            teamMemberDtoList.addAll(MapstructUtils.convert(teamMemberMapper.selectList(predicate), TeamMemberDto.class));
        }
        return new ArrayList<>(teamMemberDtoList);
    }

    @Override
    public List<TeamMemberDto> getMemberByTeamId(Integer teamId) {
        QueryWrapper<TeamMember> predicate = QueryHelpMybatisPlus.getPredicate(new TeamMemberQueryParam());
        predicate.eq("team_id", teamId);
        return MapstructUtils.convert(teamMemberMapper.selectList(predicate), TeamMemberDto.class);

    }

    @Override
    public boolean addMembers(List<TeamMemberDto> teamMemberDtos) {
        Team team = teamMapper.selectById(teamMemberDtos.get(0).getTeamId());
        TeamMemberQueryParam query = new TeamMemberQueryParam();
        query.setTeamId(String.valueOf(team.getId()));
        List<TeamMemberDto> teamMemberDtoList = queryAll(query);

        //设置默认角色
        String roleId = null;
        String defaultRole = team.getDefaultRole();
        if (defaultRole == null) {
            //没有设置默认角色的情况
            List<TeamRoleDto> teamRoleDtos = teamRoleService.getRole(String.valueOf(team.getId()));
            if (teamRoleDtos.size() <= 1) {
                throw new RuntimeException("请设置至少一个除所有者以外的角色！");
            }
            int rank = 0;
            for (TeamRoleDto teamRoleDto : teamRoleDtos) {
                if (teamRoleDto.getRank() > rank && teamRoleDto.getRank() != 1) {
                    roleId = String.valueOf(teamRoleDto.getId());
                }
            }
        } else {
            roleId = defaultRole;
        }

        for (TeamMemberDto teamMemberDto : teamMemberDtos) {
            //跳过处理原有的成员对象
            boolean b = true;
            for (TeamMemberDto memberDto : teamMemberDtoList) {
                if (teamMemberDto.getObjectId().equals(memberDto.getObjectId()) && teamMemberDto.getObjectType() == memberDto.getObjectType()) {
                    b = false;
                    break;
                }
            }
            if (b) {
                if (teamMemberDto.getRoleId() == null) {
                    //如果没有指定角色 默认为权限最小的角色
                    teamMemberDto.setRoleId(roleId);
                }

                insert(teamMemberDto);

                //头节点继承团队成员 设置默认权限
                headNodeExtendTeamMember(teamMemberDto, String.valueOf(team.getId()), team.getHeadNodeId());
            }
        }
        return true;
    }

//    @Override
//    public boolean delete(TeamMemberDto teamMemberDto) {
//        //获取该对象下的所有成员用户
//        List<FileUserDto> fileUserDtos = getUserByTeamMemberDto(teamMemberDto);
//
//        //删除成员
//        Map<String, Object> columnMap = new HashMap<>();
//        columnMap.put("team_id", teamMemberDto.getTeamId());
//        columnMap.put("object_id", teamMemberDto.getObjectId());
//        columnMap.put("object_type", teamMemberDto.getObjectType());
//        teamMemberMapper.deleteByMap(columnMap);
//
//        Set<Long> userIds = fileUserDtos.stream().map(FileUserDto::getId).collect(Collectors.toSet());
//        //获取出该团队的其他成员对象 并遍历
//        List<TeamMemberDto> memberByTeamId = getMemberByTeamId(teamMemberDto.getTeamId());
//        for (TeamMemberDto teamMemberDto1 : memberByTeamId) {
//            List<FileUserDto> otherUserIds = getUserByTeamMemberDto(teamMemberDto1);
//            //过滤其他没有成员对象中包含的成员
//            userIds.removeAll(otherUserIds.stream().map(FileUserDto::getId).collect(Collectors.toList()));
//        }
//
//        if (userIds.size() > 0){
//            //将该用户的所有者权限替换为团队所有者
//            teamRelevanceRoleService.replaceOwnerPerm(teamMemberDto.getTeamId(), userIds);
//            //删除该用户剩余的文档权限
//            teamRelevanceRoleService.removeByObjectIds(teamMemberDto.getTeamId(),PermTypeEnum.USER.getPermTypeCode(),userIds);
//        }
//
//        if (teamMemberDto.getObjectType().equals(PermTypeEnum.USER.getPermTypeCode())) {
//            //删除用户成员时 只删除用户在该团队根目录权限
//            Team team = teamMapper.selectById(teamMemberDto.getTeamId());
//            columnMap.put("tree_node_id", team.getHeadNodeId());
//        }
//        //删除该成员对文档的权限
//        teamRelevanceRoleService.removeByMap(columnMap);
//        return true;
//    }

    @Override
    public boolean delete(TeamMemberDto teamMemberDto) {

        // 删除成员
        Map<String, Object> columnMap = new HashMap<>();
        columnMap.put("team_id", teamMemberDto.getTeamId());
        columnMap.put("object_id", teamMemberDto.getObjectId());
        columnMap.put("object_type", teamMemberDto.getObjectType());
        teamMemberMapper.deleteByMap(columnMap);


        if (teamMemberDto.getObjectType().equals(PermTypeEnum.USER.getPermTypeCode())) {


            // 删除用户成员时只删除用户在该团队根目录权限
            Team team = teamMapper.selectById(teamMemberDto.getTeamId());
            columnMap.put("tree_node_id", team.getHeadNodeId());
            // 将该用户的所有者权限替换为团队所有者
            teamRelevanceRoleService.replaceOwnerPerm(teamMemberDto.getTeamId(), teamMemberDto.getObjectId());
            // 删除该用户剩余的文档权限
            teamRelevanceRoleService.removeByObjectIds(teamMemberDto.getTeamId(), PermTypeEnum.USER.getPermTypeCode(), teamMemberDto.getObjectId());
        }
        // 删除该成员对文档的权限
        teamRelevanceRoleService.removeByMap(columnMap);

        return true;
    }

//    /**
//     * 根据成员对象获取该对象所包含的用户
//     *
//     * @param teamMemberDto
//     * @return
//     */
//    private List<FileUserDto> getUserByTeamMemberDto(TeamMemberDto teamMemberDto) {
//        List<FileUserDto> userIds = new ArrayList<>();
//        if (teamMemberDto.getObjectType().equals(PermTypeEnum.USER.getPermTypeCode())) {
//            //用户类型
//            userIds.add(FileUserUtils.getUserInfo(String.valueOf(teamMemberDto.getObjectId())));
//        } else if (teamMemberDto.getObjectType().equals(PermTypeEnum.DEPT.getPermTypeCode())) {
//            //部门类型
//            UserQueryParam userQueryParam = new UserQueryParam();
//
//            userQueryParam.setEnabled(true);
//            if (!ObjectUtils.isEmpty(teamMemberDto.getObjectId())) {
//                userQueryParam.getDeptIds().add(teamMemberDto.getObjectId());
//                userQueryParam.getDeptIds().addAll(deptService.getDeptChildren(teamMemberDto.getObjectId(),
//                        deptService.findByPid(teamMemberDto.getObjectId())));
//            }
//
//            List<UserDto> userDtos = userService.queryAll(userQueryParam);
//            for (UserDto userDto : userDtos) {
//                userIds.add(FileUserUtils.getUser(userDto.getUsername()));
//            }
//        } else if (teamMemberDto.getObjectType().equals(PermTypeEnum.ROLE.getPermTypeCode())) {
//            //系统角色类型
//            List<SysUserDto> userByRole = userService.getUserByRole(teamMemberDto.getObjectId());
//            for (SysUserDto user : userByRole) {
//                userIds.add(FileUserUtils.getUser(user.getUsername()));
//            }
//        } else if (teamMemberDto.getObjectType().equals(PermTypeEnum.JOB.getPermTypeCode())) {
//            //岗位类型
//            List<SysUserDto> userByRole = userService.getUserByJob(teamMemberDto.getObjectId());
//            for (SysUserDto user : userByRole) {
//                userIds.add(FileUserUtils.getUser(user.getUsername()));
//            }
//        }
//        return userIds;
//    }

    @Override
    public void headNodeExtendTeamMember(TeamMemberDto teamMemberDto, String teamId, String headNodeId) {
        TeamRelevanceRoleDto teamRelevanceRoleDto = new TeamRelevanceRoleDto();
        teamRelevanceRoleDto.setTeamId(teamId);
        teamRelevanceRoleDto.setRoleId(teamMemberDto.getRoleId());
        teamRelevanceRoleDto.setTreeNodeId(headNodeId);
        teamRelevanceRoleDto.setObjectId(teamMemberDto.getObjectId());
        teamRelevanceRoleDto.setObjectType(teamMemberDto.getObjectType());
        teamRelevanceRoleService.insert(teamRelevanceRoleDto);
    }

    @Override
    public TeamMember getById(Integer id) {
        return teamMemberMapper.selectById(id);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public int insert(TeamMemberDto resources) {
//        String type = resources.getType();
//        Long typeId = resources.getTypeId();
//        resources.setTypeName(authorityMethod.setName(type, typeId));
        TeamMember entity = MapstructUtils.convert(resources, TeamMember.class);

        return teamMemberMapper.insert(entity);
    }


    @Override
    @Transactional(rollbackFor = Exception.class)
    public int updateById(TeamMemberDto resources) {
        TeamMember entity = MapstructUtils.convert(resources, TeamMember.class);
        int ret = teamMemberMapper.updateById(entity);
        // delCaches(resources.id);
        return ret;
    }

    @Override
    public int updateByUserId(Integer teamId, Long objectId, int objectType, String roleId) {
        return teamMemberMapper.updateByUserId(teamId, objectId, objectType, roleId);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public int removeByIds(Set<Integer> ids) {
        // delCaches(ids);
        return teamMemberMapper.deleteBatchIds(ids);
    }

    @Override
    public Boolean checkPermission(String teamId, LoginUser user, String param) {
        List<TeamMemberDto> teamMemberDtoList = getRole(teamId, user);
        boolean b = false;
        for (TeamMemberDto teamMemberDto : teamMemberDtoList) {
            TeamRole teamRole = teamRoleService.getById(teamMemberDto.getRoleId());
            if (TeamUtils.haveParam(teamRole.getParams(), param)) {
                b = true;
                break;
            }
        }
        return b;
    }

    @Override
    public List<TeamMemberDto> getRole(String teamId, LoginUser user) {
        //查询出用户在该团队所拥有成员对象
        TeamMemberQueryParam query = new TeamMemberQueryParam();
        QueryWrapper<TeamMember> predicate = QueryHelpMybatisPlus.getPredicate(query);
        //查出该团队的所有成员对象
        predicate.eq("team_id", teamId);
        List<TeamMember> teamMembers = teamMemberMapper.selectList(predicate);
        List<TeamMember> teamMemberList = new ArrayList<>();
        for (TeamMember teamMember : teamMembers) {
            //判断用户类型
            if (teamMember.getObjectType().equals(PermTypeEnum.USER.getPermTypeCode()) && teamMember.getObjectId().equals(user.getUserId())) {
                teamMemberList.add(teamMember);
                break;
            }
            //判断部门类型
            if (teamMember.getObjectType().equals(PermTypeEnum.DEPT.getPermTypeCode())) {
                Long deptId = user.getDeptId();
                if (teamMember.getObjectId().equals(deptId)) {
                    teamMemberList.add(teamMember);
                    break;
                } else {
                    List<RemoteDeptVo> deptDtos = sysDeptService.queryLowerLevel(Long.valueOf(teamMember.getObjectId()));
                    //查询出所有下级部门
                    for (RemoteDeptVo deptDto : deptDtos) {
                        if (teamMember.getObjectId().equals(deptDto.getDeptId())) {
                            teamMemberList.add(teamMember);
                            break;
                        }
                    }
                }
                //判断系统角色类型
                if (teamMember.getObjectType().equals(PermTypeEnum.ROLE.getPermTypeCode())) {
                    //获取该用户的所有角色进行判断
                    List<RoleDTO> roles = user.getRoles();
                    for (RoleDTO role : roles) {
                        if (teamMember.getObjectId().equals(role.getRoleId())) {
                            teamMemberList.add(teamMember);
                            break;
                        }
                    }
                }
                //判断岗位类型
                if (teamMember.getObjectType().equals(PermTypeEnum.JOB.getPermTypeCode())) {
                    //获取该用户的所有角色进行判断
                    List<Long> postIds = user.getPostIds();
                    for (Long postId : postIds) {
                        if (teamMember.getObjectId().equals(postId)) {
                            teamMemberList.add(teamMember);
                            break;
                        }
                    }
                }
            }
        }
        return MapstructUtils.convert(teamMemberList, TeamMemberDto.class);
    }

    @Override
    public List<TeamMemberDto> getByRoleId(Long roleId) {
        TeamMemberQueryParam query = new TeamMemberQueryParam();
        QueryWrapper<TeamMember> predicate = QueryHelpMybatisPlus.getPredicate(query);
        predicate.eq("role_id", roleId);
        return MapstructUtils.convert(teamMemberMapper.selectList(predicate), TeamMemberDto.class);
    }

    @Override
    public Set<UserHideInfoDto> queryUser(TeamMemberQueryParam query) {
        //查询出用户在该团队所拥有成员对象

        Set<UserHideInfoDto> set = new HashSet<>();

        //获取用户类型
        List<TeamMember> teamMembersUser = teamMemberMapper.queryByObjectType(query.getTeamId(), query.getNickName(), PermTypeEnum.USER.getPermTypeCode());
        teamMembersUser.forEach(teamMemberDto -> set.add(MapstructUtils.convert(LoginHelper.getLoginUser(String.valueOf(teamMemberDto.getObjectId())), UserHideInfoDto.class)));
        //获取部门类型用户
        List<TeamMember> teamMembersDept = teamMemberMapper.queryByObjectType(query.getTeamId(), null, PermTypeEnum.DEPT.getPermTypeCode());
        Set<Long> deptIds = new HashSet<>();
        for (TeamMember teamMember : teamMembersDept) {
            if (!ObjectUtils.isEmpty(teamMember.getObjectId())) {
                deptIds.add(teamMember.getObjectId());
                List<RemoteDeptVo> superiorAll = sysDeptService.getSuperiorAll(teamMember.getObjectId());
                superiorAll.forEach(remoteDeptVo -> deptIds.add(remoteDeptVo.getDeptId()));
            }
        }
        set.addAll(teamMemberMapper.queryUserByDeptIds(deptIds, query.getNickName()));
        //获取角色类型用户
        List<TeamMember> teamMembersRole = teamMemberMapper.queryByObjectType(query.getTeamId(), null, PermTypeEnum.ROLE.getPermTypeCode());
        for (TeamMember teamMember : teamMembersRole) {
            set.addAll(teamMemberMapper.queryUserByRoleId(teamMember.getObjectId(), query.getNickName()));
        }
        //获取岗位类型用户
        List<TeamMember> teamMembersJob = teamMemberMapper.queryByObjectType(query.getTeamId(), null, PermTypeEnum.JOB.getPermTypeCode());
        for (TeamMember teamMember : teamMembersJob) {
            set.addAll(teamMemberMapper.queryUserByJobId(teamMember.getObjectId(), query.getNickName()));
        }
        return set;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public int removeById(Integer id) {
        Set<Integer> set = new HashSet<>(1);
        set.add(id);
        return this.removeByIds(set);
    }
}
